#pragma once

#include <iostream>
#include <string>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <strings.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <functional>

#include <sys/wait.h>

#include "Log.hpp"
#include "InetAddr.hpp"

#include "Socket.hpp"
#include "Protocol.hpp"

using namespace Space_Socket;
const static int backlog = 16;

using io_server = std::function<void(sock_ptr,InetAddr)>;
class TcpServer;
//V2多线程时的封装
class ThreadData
{
public:
//注意InetAddr是自定义类型，拷贝构造函数是默认生成的浅拷贝，此处不影响
    ThreadData(sock_ptr sockfd,InetAddr addr,TcpServer* tps):_sockfd(sockfd),_addr(addr)
    {
        self = tps;
    }

    ~ThreadData()
    {}

    sock_ptr _sockfd;
    InetAddr _addr;
    TcpServer* self;
};

class TcpServer
{
public:
    TcpServer(int port,io_server server)
        :_local("0",port)
        ,_isrunning(false)
        ,_server(server)
    {
        _listen_sockfd = std::make_unique<TcpSocket>();
        _listen_sockfd->BuildTcpServerSocket(_local);
    }

   
    //成员函数，去掉this指针，但是又需要this指针
    static void* HandleTask(void * args)
    {
        pthread_detach(pthread_self());

        ThreadData* td = static_cast<ThreadData*>(args);
        //要让td执行Server（私有），得要有this指针
        
        td->self->_server(td->_sockfd,td->_addr);
        ::close(td->_sockfd->GetSockfd());
        delete td;
        return nullptr;
    }
    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            InetAddr one_peer;
            sock_ptr ret = _listen_sockfd->AcceptSocketOrDie(&one_peer);
            if(ret == nullptr)
            {
                continue;
            }

            //V2:多线程版本
            //要让线程看到的参数有sockfd、和addr
            //可以用类来封装
            pthread_t id;
            //传给HandleTask的是一个指针
            ThreadData* td = new ThreadData(ret,one_peer,this);
            pthread_create(&id,nullptr,HandleTask,td);//主线程要等待副线程，可以将线程分离
        }
        _isrunning = false;
    }

    ~TcpServer()
    {
       
    }

private:
    std::unique_ptr<Socket> _listen_sockfd;

    InetAddr _local;
 
    bool _isrunning;

    io_server _server;
};





//Tcp服务中，既有share_ptr,也有unique_ptr，为什么
//Tcp服务中本来就有两套套接字，unique_ptr用来accept
//shared-ptr有好几个